package cn.tuling.standard;

public class BuilderTest {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder1();
        Director director = new Director(builder);
        Product product = director.constructProduct();
        System.out.println(product.show());
    }
}

class Product {
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    public String show() {
        return "Product{" +
                "partA='" + partA + '\'' +
                ", partB='" + partB + '\'' +
                ", partC='" + partC + '\'' +
                '}';
    }
}

abstract class Builder {
    protected Product product = new Product();

    protected abstract void buildPartA();

    protected abstract void buildPartB();

    protected abstract void buildPartC();

    protected Product getResult() {
        return product;
    }
}

/**
 * 1和2创建过程可能不一样
 */
class ConcreteBuilder1 extends Builder {

    @Override
    protected void buildPartA() {
        product.setPartA("1-A部件");
    }

    @Override
    protected void buildPartB() {
        product.setPartB("1-B部件");
    }

    @Override
    protected void buildPartC() {
        product.setPartC("1-C部件");
    }
}

class ConcreteBuilder2 extends Builder {

    @Override
    protected void buildPartA() {
        product.setPartA("2-A部件");
    }

    @Override
    protected void buildPartB() {
        product.setPartB("2-B部件");
    }

    @Override
    protected void buildPartC() {
        product.setPartC("3-C部件");
    }
}

/**
 * 若想实现组装顺序的可选、随意控制，且符合开闭原则，要将控制类抽象成接口。
 */
class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product constructProduct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}